package net.wds.ssbus.common.aspect;

import javassist.*;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import net.wds.ssbus.common.annotation.SsbusLog;
import net.wds.ssbus.modules.ssbus.pojo.TbSsbusLogEntrty;
import net.wds.ssbus.modules.ssbus.service.TbSsbusLogService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Aspect
@Component
public class SsbusLogAspect {



    @Autowired
    private TbSsbusLogService tbSsbusLogService;
    TbSsbusLogEntrty  ssbusLogentrty= new TbSsbusLogEntrty();



    @Pointcut("@annotation(net.wds.ssbus.common.annotation.SsbusLog)")
    public void logPointCut() {

    }

    ServletRequestAttributes attributes1;
    HttpServletRequest request1;
    HttpSession session;

    /**
     * ssbus日志执行方法
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {

        long beginTime = System.currentTimeMillis();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        Exception e = new Exception();
        //保存日志
        saveSsbusLog(point, time,e);
        //执行方法
        Object result=null;
        try {
            result = point.proceed();
       } catch (Exception e1)
        {
            ssbusLogentrty.setExceptionmessagecause(e1.toString());//捕获到错误的异常原因
            attributes1 = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            request1 = attributes1.getRequest();
            session = request1.getSession();
            ssbusLogentrty.setExceptionmessage("失败"+session.getAttribute("result"));

        }
        System.out.println(result+"----------------");
        return result;
    }

    /**
     * 保存系统日志
     */

    private void saveSsbusLog(ProceedingJoinPoint proceedingJoinPoint, long time, Exception e) {

        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        SsbusLog ssbusLog = method.getAnnotation(SsbusLog.class);
        if (ssbusLog != null) {
            //注解上的描述
            System.out.println(ssbusLog.value());
        }
        //获取servlet请求对象---因为这不是控制器，这里不能注入HttpServletRequest，但springMVC本身提供ServletRequestAttributes可以拿到
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        System.out.println("发送请求的路径:" + request.getRequestURL().toString());
        System.out.println("请求提交的方式:" + request.getMethod());
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        String methodName = proceedingJoinPoint.getSignature().getName();
        System.out.println("异常的信息:" + e.getMessage());
        Class<?> clazz = null;
        try {
            clazz= Class.forName(className);

        } catch (ClassNotFoundException classNotFoundException) {

            classNotFoundException.printStackTrace();
        }
        String clazzName = clazz.getName();
        Object[] args1 = proceedingJoinPoint.getArgs();//参数
        //获取参数名称和值
        Map<String,Object > nameAndArgs = null;
        try {
            nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName,args1);  //1, 2,异常所在的类 3, 方法的名称,传递过来的参数

        } catch (NotFoundException notFoundException) {

            notFoundException.printStackTrace();
        }
    }

    private Map<String,Object> getFieldsName(Class cls, String clazzName, String methodName, Object[] args) throws NotFoundException {
        Map<String,Object > map=new HashMap<String,Object>();
        ClassPool pool = ClassPool.getDefault();
        ClassClassPath classPath = new ClassClassPath(cls);
        pool.insertClassPath(classPath);
        System.out.println("异常所在类：" + clazzName);
        CtClass cc = pool.get(clazzName);
        ssbusLogentrty.setExceptionclassname(clazzName);
        System.out.println("异常所在方法：" + methodName);
        CtMethod cm = cc.getDeclaredMethod(methodName);
        MethodInfo methodInfo = cm.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
        if (attr == null) {
            // exception
        }
        // String[] paramNames = new String[cm.getParameterTypes().length];
        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
        for (int i = 0; i < cm.getParameterTypes().length; i++){
            map.put( attr.variableName(i + pos),args[i]);//paramNames即参数名
        }

        //Map<>
        return map;
    }
    /**
     * 处理完请求返回内容
     * @param
     * @throws Throwable
     */
    @AfterReturning(returning = "object", pointcut = "logPointCut()")
    public void doAfterReturning(Object object) throws Throwable {
        // 处理完请求，返回内容
            attributes1 = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            request1 = attributes1.getRequest();
            session = request1.getSession();
            String name =(String)session.getAttribute("name");
            String id =(String)session.getAttribute("id");
            ssbusLogentrty.setLogLevel("E");
            ssbusLogentrty.setTaskname(name);
            ssbusLogentrty.setTasktime(new Date());
            ssbusLogentrty.setThreadname(id);
            String e=(String)session.getAttribute("e");
            ssbusLogentrty.setExceptionmessagecause(e);
            ssbusLogentrty.setData(object.toString());
            ssbusLogentrty.setExceptionmessage("失败");
            ssbusLogentrty.setId(UUID.randomUUID().toString().toLowerCase());
            tbSsbusLogService.save(ssbusLogentrty);

        //System.out.println(object.toString());
        //System.out.println(session.getAttribute("name")+"任务名称");

    }
}
